﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using YArchitech.LIB;
using YArchitech.Revit;
using YJKOpeningCommon.DataEnum;
using YJKOpeningCommon.DbOpening;
using YJKOpeningCommon.OpeningProfile;
using YJKOpeningCommon.Public;
using YJKRGeometry;
using YJKRGeometry.CalculationAnalysis;

namespace YJKOpeningDesignInput.Public
{
	internal class Interface
	{
		public static bool GetXmlData(ref Dictionary<string, int> xmlData)
		{
			bool result;
			try
			{
				string text = Product.UserDataLocation + "\\OpeningDesignSetReportForm.xml";
				XmlDocument xmlDocument = new XmlDocument();
				if (File.Exists(text))
				{
					XmlReader xmlReader = XmlReader.Create(text, new XmlReaderSettings
					{
						IgnoreComments = true
					});
					xmlDocument.Load(xmlReader);
					XmlNode xmlNode = xmlDocument.SelectSingleNode("HistoryData");
					int value = Convert.ToInt32(xmlNode.Attributes["LocationX"].Value);
					xmlData.Add("LocationX", value);
					value = Convert.ToInt32(xmlNode.Attributes["LocationY"].Value);
					xmlData.Add("LocationY", value);
					value = Convert.ToInt32(xmlNode.Attributes["CircleOpeningOutSize"].Value);
					xmlData.Add("CircleOpeningOutSize", value);
					value = Convert.ToInt32(xmlNode.Attributes["RectOpeningOutSize"].Value);
					xmlData.Add("RectOpeningOutSize", value);
					value = Convert.ToInt32(xmlNode.Attributes["CompositeTolerance"].Value);
					xmlData.Add("CompositeTolerance", value);
					value = Convert.ToInt32(xmlNode.Attributes["CompositeOutSize"].Value);
					xmlData.Add("CompositeOutSize", value);
					xmlReader.Close();
					xmlDocument.Save(text);
				}
				else
				{
					xmlData.Add("CircleOpeningOutSize", 50);
					xmlData.Add("RectOpeningOutSize", 50);
					xmlData.Add("CompositeOutSize", 50);
					xmlData.Add("CompositeTolerance", 300);
				}
				result = true;
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

		public static void SetOpeningExternDist(ref DbOpeningBase dbOpeningBase, Dictionary<string, int> dictionary)
		{
			if (dbOpeningBase.m_profile is OpeningProfileCircle)
			{
				dbOpeningBase.m_profile.m_dExtendDist = AssistFunc.mmToFeet((double)dictionary["CircleOpeningOutSize"]);
			}
			else if (dbOpeningBase.m_profile is OpeningProfileRect)
			{
				if (dbOpeningBase is DbCompositeRectFloorOpening || dbOpeningBase is DbCompositeRectWallOpening)
				{
					dbOpeningBase.m_profile.m_dExtendDist = AssistFunc.mmToFeet((double)dictionary["CompositeOutSize"]);
				}
				else
				{
					dbOpeningBase.m_profile.m_dExtendDist = AssistFunc.mmToFeet((double)dictionary["RectOpeningOutSize"]);
				}
			}
			dbOpeningBase.m_profile.m_dTolerance = AssistFunc.mmToFeet((double)dictionary["CompositeTolerance"]);
		}

		private static bool GetBeamWidth(FamilyInstance familyIns, ref double width)
		{
			try
			{
				LocationCurve locationCurve = familyIns.Location as LocationCurve;
				Line line = locationCurve.Curve as Line;
				if (line == null)
				{
					return false;
				}
				XYZ hyendPoint = line.GetEndPoint(0);
				XYZ hyendPoint2 = line.GetEndPoint(1);
				XYZ xyz = (hyendPoint2 - hyendPoint).Normalize();
				List<Face> list = new List<Face>();
				if (!Interface.GetAllFace(familyIns, ref list, xyz, familyIns.Document.ActiveView))
				{
					return false;
				}
				foreach (Face face in list)
				{
					PlanarFace planarFace = face as PlanarFace;
					if (!(null == planarFace))
					{
						XYZ xyz2 = planarFace.FaceNormal.Normalize();
						if (xyz.IsAlmostEqualTo(xyz2) || xyz.IsAlmostEqualTo(xyz2.Negate()))
						{
							EdgeArrayArray edgeLoops = planarFace.EdgeLoops;
							if (edgeLoops.Size == 1)
							{
                                EdgeArray edgeArray = edgeLoops.get_Item(0);
								if (edgeArray.Size == 4)
								{
									IEnumerator enumerator2 = edgeArray.GetEnumerator();
									{
										while (enumerator2.MoveNext())
										{
											object obj = enumerator2.Current;
											Edge edge = (Edge)obj;
											Curve curve = edge.AsCurve();
											Line line2 = curve as Line;
											if (!(line2 == null))
											{
												hyendPoint = line2.GetEndPoint(0);
												hyendPoint2 = line2.GetEndPoint(1);
												double val = hyendPoint.DistanceTo(hyendPoint2);
												if (Math.Abs(hyendPoint.Z - hyendPoint2.Z) < 0.0001)
												{
													width = Math.Max(width, val);
												}
											}
										}
										break;
									}
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private static bool GetSubjectWidth(Element elem, ref double width)
		{
			CompoundStructure compoundStructure = null;
			if (elem is Wall)
			{
				Wall wall = elem as Wall;
				WallType wallType = wall.WallType;
				compoundStructure = wallType.GetCompoundStructure();
			}
			else if (elem is Floor)
			{
				Floor floor = elem as Floor;
				FloorType floorType = floor.FloorType;
				compoundStructure = floorType.GetCompoundStructure();
			}
			if (compoundStructure == null)
			{
				width = -0.1;
				return false;
			}
			IList<CompoundStructureLayer> layers = compoundStructure.GetLayers();
			foreach (CompoundStructureLayer compoundStructureLayer in layers)
			{
				width += compoundStructureLayer.Width;
			}
			return true;
		}

		private static bool GetCutAngle(Element cutElem, ref double dAngle)
		{
			try
			{
				ConnectorManager connectorManager = null;
				if (cutElem is Duct)
				{
					Duct duct = cutElem as Duct;
					connectorManager = duct.ConnectorManager;
				}
				else if (cutElem is CableTray)
				{
					CableTray cableTray = cutElem as CableTray;
					connectorManager = cableTray.ConnectorManager;
				}
				if (connectorManager == null)
				{
					return false;
				}
				ConnectorSet connectors = connectorManager.Connectors;
				if (connectors.Size == 0)
				{
					return false;
				}
				Connector connector = null;
				IEnumerator enumerator = connectors.GetEnumerator();
				{
					if (enumerator.MoveNext())
					{
						Connector connector2 = (Connector)enumerator.Current;
						connector = connector2;
					}
				}
				if (connector == null)
				{
					return false;
				}
				XYZ basisX = connector.CoordinateSystem.BasisX;
				dAngle = basisX.AngleTo(XYZ.BasisX);
			}
			catch (Exception)
			{
				throw;
			}
			return true;
		}

		private static bool GetOpeningOritation(Element hostElem, ref OpeningData openingData)
		{
			try
			{
				if (hostElem is Wall)
				{
					Wall wall = hostElem as Wall;
					Curve elemLocationCurve = Interface.GetElemLocationCurve(hostElem);
					if (elemLocationCurve == null)
					{
						return false;
					}
					if (elemLocationCurve as Line != null)
					{
						openingData.m_openingDirection = wall.Orientation.Normalize();
						return true;
					}
					Arc arc = elemLocationCurve as Arc;
					if (arc != null && !CommonInterface.GetCurveOritation(openingData.m_position, arc, ref openingData.m_openingDirection))
					{
						return false;
					}
				}
				else if (hostElem is Floor)
				{
					openingData.m_openingDirection = XYZ.BasisZ;
				}
				else if (hostElem is FamilyInstance && hostElem.Category.Id.IntegerValue == -2001320)
				{
					FamilyInstance familyInstance = hostElem as FamilyInstance;
					openingData.m_openingDirection = familyInstance.FacingOrientation.Normalize();
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private static bool GetOpeningData(Element elem, ref OpeningData openingData, XYZ localPt)
		{
			try
			{
				openingData.m_position = localPt;
				if (!Interface.GetOpeningOritation(elem, ref openingData))
				{
					return false;
				}
				openingData.m_strOpeningGuid = Guid.NewGuid().ToString();
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		private static bool GetLevel(Element elem, ref string strLevel)
		{
			bool result;
			try
			{
				ElementId levelId = elem.LevelId;
				if (levelId.IntegerValue == -1 && elem is FamilyInstance)
				{
					FamilyInstance familyInstance = elem as FamilyInstance;
					strLevel = familyInstance.Host.Name;
					result = true;
				}
				else
				{
					Document document = elem.Document;
					Element element = document.GetElement(levelId);
					strLevel = element.Name;
					result = true;
				}
			}
			catch (Exception)
			{
				strLevel = "";
				result = true;
			}
			return result;
		}

		private static bool GetHostData(Element subElem, ref OpeningData openingData)
		{
			try
			{
				double hostWidth = 0.0;
				if (subElem is Wall)
				{
					if (!Interface.GetSubjectWidth(subElem, ref hostWidth))
					{
						return false;
					}
					openingData.m_eSubObject = CommonInterface.GetSubjectObj(subElem);
				}
				if (subElem is Floor)
				{
					if (!Interface.GetSubjectWidth(subElem, ref hostWidth))
					{
						return false;
					}
					openingData.m_eSubObject = EHostObject.eStruFloor;
				}
				else if (subElem is FamilyInstance)
				{
					FamilyInstance familyIns = subElem as FamilyInstance;
					if (!Interface.GetBeamWidth(familyIns, ref hostWidth))
					{
						return false;
					}
					openingData.m_eSubObject = EHostObject.eBeam;
				}
				openingData.m_hostWidth = hostWidth;
				openingData.m_strHostUniqueId = subElem.UniqueId;
				string empty = string.Empty;
				if (!Interface.GetLevel(subElem, ref empty))
				{
					return false;
				}
				openingData.m_strFloorPlan = empty;
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public static bool GetCutData(Element cutElem, ref OpeningData openingData)
		{
			double cutWidth = 0.0;
			double cutHeight = 0.0;
			double cutDia = 0.0;
			try
			{
				if (cutElem is Duct)
				{
					Duct elemCurve = cutElem as Duct;
					if (!Interface.GetMEPSize(elemCurve, ref cutWidth, ref cutHeight))
					{
						return false;
					}
					openingData.m_eCutObject = ECutObject.eDuct;
					openingData.m_eSpeciaObject = ESpeciality.eHvac;
				}
				else if (cutElem is CableTray)
				{
					CableTray elemCurve2 = cutElem as CableTray;
					if (!Interface.GetMEPSize(elemCurve2, ref cutWidth, ref cutHeight))
					{
						return false;
					}
					openingData.m_eCutObject = ECutObject.eCableTray;
					openingData.m_eSpeciaObject = ESpeciality.eElec;
				}
				else if (cutElem is Pipe)
				{
					Pipe elemCurve3 = cutElem as Pipe;
					if (!Interface.GetMEPSize(elemCurve3, ref cutDia, ref cutHeight))
					{
						return false;
					}
					int disciplineValue = Product.GetDisciplineValue();
					if (disciplineValue == 2)
					{
						openingData.m_eCutObject = ECutObject.eHvPipe;
						openingData.m_eSpeciaObject = ESpeciality.eHvac;
					}
					else if (disciplineValue == 4)
					{
						openingData.m_eCutObject = ECutObject.eWaterPipe;
						openingData.m_eSpeciaObject = ESpeciality.ePipe;
					}
					else
					{
						openingData.m_eCutObject = ECutObject.ePipeMulti;
						openingData.m_eSpeciaObject = ESpeciality.eMulti;
					}
				}
				openingData.m_cutDia = cutDia;
				openingData.m_cutHeight = cutHeight;
				openingData.m_cutWidth = cutWidth;
				XYZ zero = XYZ.Zero;
				XYZ zero2 = XYZ.Zero;
				if (!Interface.GetElemLocationCurve(cutElem, ref zero, ref zero2))
				{
					return false;
				}
				XYZ xyz = zero2 - zero;
				openingData.m_directionCutObj = xyz.Normalize();
				string uniqueId = cutElem.UniqueId;
				openingData.m_strCutUniqueld = uniqueId;
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public static bool GetOpeningDatas(ref DbOpeningBase opening, ref OpeningData openingData, XYZ openingLocalPt, Element hostElem, Element cutElem, List<PointSort> lstInfos)
		{
			if (!Interface.GetHostData(hostElem, ref openingData))
			{
				return false;
			}
			if (!Interface.GetCutData(cutElem, ref openingData))
			{
				return false;
			}
			if (hostElem is Floor && !(cutElem is Pipe))
			{
				double cutAngle = 0.0;
				if (!Interface.GetCutAngle(cutElem, ref cutAngle))
				{
					return false;
				}
				openingData.m_cutAngle = cutAngle;
			}
			return Interface.GetOpeningData(hostElem, ref openingData, openingLocalPt) && (lstInfos == null || lstInfos.Count == 0 || Interface.GetXYGrid(openingData.m_position, lstInfos, ref openingData.m_strAxisX, ref openingData.m_strAxisY));
		}

		public static bool GetXYGrid(XYZ location, List<PointSort> lstInfos, ref string strXGrid, ref string strYGrid)
		{
			strXGrid = "";
			strYGrid = "";
			int count = lstInfos.Count;
			if (count < 1)
			{
				return true;
			}
			XYZ xyz = new XYZ(location.X, location.Y, 0.0);
			bool result;
			try
			{
				for (int i = 0; i < count; i++)
				{
					PointSort pointSort = lstInfos[i];
					pointSort.m_dParam = xyz.DistanceTo(pointSort.m_pt);
				}
				lstInfos.Sort(new Interface.PointComparer());
				strXGrid = lstInfos[0].m_lstGridName.First<string>();
				strYGrid = lstInfos[0].m_lstGridName.Last<string>();
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static bool GetOpeningDataByEquip(Element hostElem, FamilyInstance cutElem, XYZ equipCenterPt, ref OpeningData openingData, double equipMinZ, EEquipType equipType)
		{
			bool result;
			try
			{
				Curve elemLocationCurve = Interface.GetElemLocationCurve(hostElem);
				IntersectionResult intersectionResult = elemLocationCurve.Project(equipCenterPt);
				XYZ xyzpoint = intersectionResult.XYZPoint;
				openingData.m_openingDirection = (equipCenterPt - xyzpoint).Normalize();
				if (equipType == EEquipType.eMechanicalEquipment)
				{
					openingData.m_eSpeciaObject = ESpeciality.ePipe;
				}
				else if (equipType == EEquipType.eElectricalEquipment)
				{
					openingData.m_eSpeciaObject = ESpeciality.eElec;
				}
				else if (equipType == EEquipType.eWaterCollectorEquipment)
				{
					openingData.m_eSpeciaObject = ESpeciality.eHvac;
				}
				openingData.m_strOpeningGuid = Guid.NewGuid().ToString();
				openingData.m_position = new XYZ(xyzpoint.X, xyzpoint.Y, equipMinZ);
				double num = xyzpoint.DistanceTo(equipCenterPt);
				if (Geometry.LessThan(openingData.m_hostWidth / 2.0, num))
				{
					openingData.m_penetrationThickness = Math.Abs(openingData.m_cutWidth / 2.0 - (num - openingData.m_hostWidth / 2.0));
				}
				else
				{
					openingData.m_penetrationThickness = openingData.m_hostWidth / 2.0 + openingData.m_cutWidth / 2.0 - num;
				}
				result = true;
			}
			catch (Exception)
			{
				throw;
			}
			return result;
		}

		private static void GetCutDataByEquip(FamilyInstance cutElem, ref OpeningData openingData, EEquipType equipType)
		{
			openingData.m_directionCutObj = cutElem.FacingOrientation.Normalize();
			if (equipType == EEquipType.eMechanicalEquipment)
			{
				openingData.m_eCutObject = ECutObject.eHydrant;
			}
			else if (equipType == EEquipType.eElectricalEquipment)
			{
				openingData.m_eCutObject = ECutObject.eDistributionBox;
			}
			else if (equipType == EEquipType.eWaterCollectorEquipment)
			{
				openingData.m_eCutObject = ECutObject.eWaterCollector;
			}
			openingData.m_strCutUniqueld = cutElem.UniqueId;
		}

		public static bool GetOpeningDatasByEquip(ref DbOpeningBase opening, ref OpeningData openingData, Element hostElem, FamilyInstance cutElem, XYZ equipCenterPt, double equipMinZ, EEquipType equipType, List<PointSort> lstInfos)
		{
			try
			{
				if (!Interface.GetHostData(hostElem, ref openingData))
				{
					return false;
				}
				Interface.GetCutDataByEquip(cutElem, ref openingData, equipType);
				if (!Interface.GetOpeningDataByEquip(hostElem, cutElem, equipCenterPt, ref openingData, equipMinZ, equipType))
				{
					return false;
				}
				if (lstInfos == null || lstInfos.Count == 0)
				{
					return true;
				}
				if (!Interface.GetXYGrid(openingData.m_position, lstInfos, ref openingData.m_strAxisX, ref openingData.m_strAxisY))
				{
					return false;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public static void SetOpeningData2Opening(OpeningData openingData, ref DbOpeningBase opening, OpeningProfileBase openingProfile)
		{
			opening.m_eHostObject = openingData.m_eSubObject;
			opening.m_eCutObject = openingData.m_eCutObject;
			opening.m_eSpeciality = openingData.m_eSpeciaObject;
			opening.m_profile = openingProfile;
			opening.m_strCutUniqueId = openingData.m_strCutUniqueld;
			opening.m_strGuid = openingData.m_strOpeningGuid;
			opening.m_strHostUniqueId = openingData.m_strHostUniqueId;
			opening.m_strAxisX = openingData.m_strAxisX;
			opening.m_strAxisY = openingData.m_strAxisY;
			opening.m_dHostWidth = openingData.m_hostWidth;
			opening.m_strFloorPlan = openingData.m_strFloorPlan;
		}

		public static void SetOpeningProfile(ref OpeningProfileBase openingProfile, OpeningData openingData)
		{
			openingProfile.m_directionCutObj = openingData.m_directionCutObj;
			openingProfile.m_directionProfile = openingData.m_openingDirection;
			XYZ directionProfile = openingProfile.m_directionProfile;
			openingProfile.m_dExtendDist = openingData.m_extendDist;
			openingProfile.m_dPenetrationThickness = openingData.m_penetrationThickness;
			openingProfile.m_position = openingData.m_position;
			openingProfile.m_dTolerance = openingData.m_tolerance;
		}

		public static List<T> GetAllIntersectSubject<T>(Element mepElem, Document doc, BuiltInCategory builtIncategory) where T : Element
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfCategory(builtIncategory).WhereElementIsNotElementType();
			ElementIntersectsElementFilter elementIntersectsElementFilter = new ElementIntersectsElementFilter(mepElem);
			filteredElementCollector.WherePasses(elementIntersectsElementFilter);
			List<T> list = new List<T>();
			foreach (Element element in filteredElementCollector)
			{
				if (element is T)
				{
					list.Add(element as T);
				}
			}
			return list;
		}

		public static Line GetMEPCurveLine(Element elem)
		{
			LocationCurve locationCurve = elem.Location as LocationCurve;
			if (locationCurve == null)
			{
				return null;
			}
			return Line.CreateBound(locationCurve.Curve.GetEndPoint(0), locationCurve.Curve.GetEndPoint(1));
		}

		private static bool GetElemLocationCurve(Element elem, ref XYZ ptStart, ref XYZ ptEnd)
		{
			if (elem == null)
			{
				return false;
			}
			Curve elemLocationCurve = Interface.GetElemLocationCurve(elem);
			if (elemLocationCurve != null)
			{
				ptStart = elemLocationCurve.GetEndPoint(0);
				ptEnd = elemLocationCurve.GetEndPoint(1);
				return true;
			}
			return false;
		}

		public static List<XYZ> GetCvIntersect2ElemPoints(Curve cv, Element elem)
		{
			List<XYZ> list = new List<XYZ>();
			List<XYZ> result;
			try
			{
				XYZ endPoint = cv.GetEndPoint(0);
				XYZ endPoint2 = cv.GetEndPoint(1);
				XYZ zero = XYZ.Zero;
				XYZ zero2 = XYZ.Zero;
				if (Interface.GetElemLocationCurve(elem, ref zero, ref zero2))
				{
					double z = zero.Z;
					XYZ xyz = new XYZ(endPoint.X, endPoint.Y, z);
					XYZ xyz2 = new XYZ(endPoint2.X, endPoint2.Y, z);
					Curve curve = Line.CreateBound(xyz, xyz2);
					IntersectionResultArray intersectionResultArray = null;
					Curve elemLocationCurve = Interface.GetElemLocationCurve(elem);
					SetComparisonResult setComparisonResult = curve.Intersect(elemLocationCurve, out intersectionResultArray);
					if (setComparisonResult == SetComparisonResult.Overlap)
					{
						for (int i = 0; i < intersectionResultArray.Size; i++)
						{
							XYZ xyzpoint = intersectionResultArray.get_Item(i).XYZPoint;
							Line line = Line.CreateUnbound(xyzpoint, XYZ.BasisZ);
							IntersectionResultArray intersectionResultArray2 = null;
                            if ((int)line.Intersect(cv, out intersectionResultArray2) == 8 && intersectionResultArray2.Size > 0)
							{
								xyzpoint = intersectionResultArray2.get_Item(0).XYZPoint;
								list.Add(xyzpoint);
							}
						}
					}
				}
				result = list;
			}
			catch (Exception)
			{
				result = list;
			}
			return result;
		}

		private static Curve GetElemLocationCurve(Element elem)
		{
			if (elem == null)
			{
				return null;
			}
			LocationCurve locationCurve = elem.Location as LocationCurve;
			if (locationCurve != null)
			{
				return locationCurve.Curve;
			}
			return null;
		}

		public static bool GetMEPSize(MEPCurve elemCurve, ref double dW, ref double dH)
		{
			try
			{
				if (elemCurve is Duct)
				{
					Duct duct = elemCurve as Duct;
					Parameter parameter = duct.get_Parameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
					parameter.AsDouble();
					dW = parameter.AsDouble();
					Parameter parameter2 = duct.get_Parameter(BuiltInParameter.RBS_CURVE_HEIGHT_PARAM);
					dH = parameter2.AsDouble();
				}
				else if (elemCurve is CableTray)
				{
					CableTray cableTray = elemCurve as CableTray;
					Parameter parameter3 = cableTray.get_Parameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM);
					dW = parameter3.AsDouble();
					Parameter parameter4 = cableTray.get_Parameter(BuiltInParameter.RBS_CABLETRAY_HEIGHT_PARAM);
					dH = parameter4.AsDouble();
				}
				else
				{
					if (!(elemCurve is Pipe))
					{
						throw new Exception("无效的实体类型");
					}
					Pipe pipe = elemCurve as Pipe;
					Parameter parameter5 = pipe.get_Parameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
					dW = parameter5.AsDouble();
					dH = -1.0;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public static bool GetAllFace(Element elem, ref List<Face> lstFace, XYZ normal, View view = null)
		{
			bool result;
			try
			{
				Options options = new Options();
				options.ComputeReferences = false;
				options.IncludeNonVisibleObjects = true;
				if (view != null)
				{
					options.View = view;
				}
				else
				{
					options.DetailLevel = (ViewDetailLevel)3;
				}
				GeometryElement geometryElement = elem.get_Geometry(options);
				foreach (GeometryObject geometryObject in geometryElement)
				{
					if (geometryObject is PlanarFace)
					{
						PlanarFace planarFace = geometryObject as PlanarFace;
						if (planarFace.Origin.IsAlmostEqualTo(normal) || planarFace.Origin.IsAlmostEqualTo(normal.Negate()))
						{
							lstFace.Add(geometryObject as PlanarFace);
						}
					}
					else if (geometryObject is Solid)
					{
						Solid solid = geometryObject as Solid;
						if (!Interface.GetFaceBySolid(solid, ref lstFace, normal))
						{
							return false;
						}
					}
					else if (geometryObject is GeometryInstance)
					{
						GeometryInstance geometryInstance = geometryObject as GeometryInstance;
						foreach (object obj in geometryInstance.SymbolGeometry)
						{
							Solid solid2 = obj as Solid;
							if (!Interface.GetFaceBySolid(solid2, ref lstFace, normal))
							{
								return false;
							}
						}
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static bool GetFaceBySolid(Solid solid, ref List<Face> lstFace, XYZ normal)
		{
			bool result;
			try
			{
				if (solid != null)
				{
					foreach (object obj in solid.Faces)
					{
						Face face = (Face)obj;
						if (face.GetType() == typeof(PlanarFace))
						{
							PlanarFace face2 = face as PlanarFace;
							XYZ xyz = face2.FaceNormal();
							if (xyz.Normalize().IsAlmostEqualTo(normal) || xyz.Normalize().IsAlmostEqualTo(normal.Negate()))
							{
								lstFace.Add(face);
							}
						}
						else if (face.GetType() == typeof(CylindricalFace))
						{
							lstFace.Add(face);
						}
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static XYZ TransformPoint(XYZ point, Transform transform)
		{
			return transform.OfPoint(point);
		}

		private static bool AddPt2List(XYZ addPt, ref List<XYZ> lstPt)
		{
			bool result;
			try
			{
				XYZ xyz = new XYZ(addPt.X, addPt.Y, 0.0);
				foreach (XYZ xyz2 in lstPt)
				{
					if (xyz2.IsAlmostEqualTo(xyz))
					{
						return true;
					}
				}
				lstPt.Add(xyz);
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static bool GetMirrorPoint(List<XYZ> lstPt, ref List<XYZ> lstMirPt)
		{
			bool result;
			try
			{
				foreach (XYZ addPt in lstPt)
				{
					Interface.AddPt2List(addPt, ref lstMirPt);
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static void RankAllPt(ref List<XYZ> lstPt)
		{
			for (int i = 0; i < lstPt.Count - 1; i++)
			{
				for (int j = i + 1; j < lstPt.Count; j++)
				{
					if (Geometry.LessThan(lstPt[j].Z, lstPt[i].Z))
					{
						XYZ value = lstPt[j];
						lstPt[j] = lstPt[i];
						lstPt[i] = value;
					}
				}
			}
		}

		private static bool GetAllPoint(Transform transform, List<Face> lstFace, ref List<XYZ> lstPt)
		{
			bool result;
			try
			{
				foreach (Face face in lstFace)
				{
					Mesh mesh = face.Triangulate();
					foreach (XYZ xyz in mesh.Vertices)
					{
						XYZ item = transform.OfPoint(xyz);
						lstPt.Add(item);
					}
				}
				result = true;
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static void GetGreater(double d1, double d2, ref double dMin, ref double dMax)
		{
			if (d1 - d2 <= 1E-06)
			{
				dMin = d1;
				dMax = d2;
				return;
			}
			dMin = d2;
			dMax = d1;
		}

		public static bool GetAllIntersectSubjectByEquip(KeyValuePair<FamilyInstance, StructFiBindingData> dic, ref Wall wall, Document currentDoc, Document doc, ref OpeningData openingData, ref XYZ equipCenterMirPt, ref double minZ)
		{
			bool result;
			try
			{
				FamilyInstance key = dic.Key;
				RevitLinkInstance revitLinkIns = dic.Value.RevitLinkIns;
				List<Face> lstFace = new List<Face>();
				if (!Interface.GetAllFace(key, ref lstFace, XYZ.BasisZ, null))
				{
					result = false;
				}
				else
				{
					List<XYZ> list = new List<XYZ>();
					Transform transform = key.GetTransform();
					if (!Interface.GetAllPoint(transform, lstFace, ref list) || list.Count == 0)
					{
						result = false;
					}
					else
					{
						Interface.RankAllPt(ref list);
						List<XYZ> vertexes = new List<XYZ>();
						if (!Interface.GetMirrorPoint(list, ref vertexes))
						{
							result = false;
						}
						else
						{
							List<XYZ> list2 = new List<XYZ>();
							double num = 0.0;
							double num2 = 0.0;
							if (!MinAreaBoundingBoxCalculator.MinAreaRect(vertexes, ref list2, ref num2, ref num))
							{
								result = false;
							}
							else
							{
								Interface.GetGreater(num, num2, ref num2, ref num);
								if (revitLinkIns != null)
								{
									Transform totalTransform = revitLinkIns.GetTotalTransform();
									for (int i = 0; i < list2.Count<XYZ>(); i++)
									{
										list2[i] = totalTransform.OfPoint(list2[i]);
									}
								}
								double num3 = 0.0;
								double num4 = 0.0;
								Interface.GetGreater(list2[2].X, list2[0].X, ref num3, ref num4);
								double num5 = 0.0;
								double num6 = 0.0;
								Interface.GetGreater(list2[2].Y, list2[0].Y, ref num5, ref num6);
								XYZ xyz = new XYZ(num3, num5, list[0].Z);
								XYZ xyz2 = new XYZ(num4, num6, list[list.Count - 1].Z);
								Outline outline = null;
								Transaction transaction = new Transaction(currentDoc, "outline");
								try
								{
									transaction.Start();
									outline = new Outline(xyz, xyz2);
									transaction.Commit();
								}
								catch (Exception)
								{
									transaction.RollBack();
									throw;
								}
								if (outline.IsEmpty)
								{
									result = true;
								}
								else
								{
									FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
									BoundingBoxIntersectsFilter boundingBoxIntersectsFilter = new BoundingBoxIntersectsFilter(outline);
									List<Wall> list3 = filteredElementCollector.OfClass(typeof(Wall)).WherePasses(boundingBoxIntersectsFilter).Cast<Wall>().ToList<Wall>();
									if (list3.Count == 0)
									{
										result = true;
									}
									else
									{
										List<Wall> list4 = Interface.IsInterSecterWall(list2, list3);
										if (list4.Count != 1)
										{
											result = true;
										}
										else
										{
											minZ = list[0].Z;
											wall = list4[0];
											openingData.m_cutWidth = num2;
											openingData.m_cutLength = num;
											openingData.m_cutHeight = list[list.Count - 1].Z - list[0].Z;
											Curve elemLocationCurve = Interface.GetElemLocationCurve(wall);
											XYZ endPoint = elemLocationCurve.GetEndPoint(0);
											XYZ xyz3 = (xyz + xyz2) / 2.0;
											equipCenterMirPt = new XYZ(xyz3.X, xyz3.Y, endPoint.Z);
											result = true;
										}
									}
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
				result = false;
			}
			return result;
		}

		private static List<Wall> IsInterSecterWall(List<XYZ> lstPt, List<Wall> lstWalls)
		{
			List<Curve> list = new List<Curve>();
			new List<XYZ>();
			List<Wall> list2 = new List<Wall>();
			if (lstPt.Count != 4)
			{
				return list2;
			}
			List<Curve> lstCurve = null;
			foreach (Wall wall in lstWalls)
			{
				list.Clear();
				Interface.GetElemUndersideCurve(wall, ref list);
				if (list.Count > 0)
				{
					double z = list[0].GetEndPoint(0).Z;
					for (int i = 0; i < lstPt.Count; i++)
					{
						lstPt[i] = new XYZ(lstPt[i].X, lstPt[i].Y, z);
					}
					lstCurve = Interface.CreateLines(lstPt);
				}
				if (Interface.IsIntersect(list, lstCurve))
				{
					list2.Add(wall);
				}
			}
			return list2;
		}

		private static void GetElemUndersideCurve(Wall wall, ref List<Curve> lstCurve)
		{
			try
			{
				List<Face> list = new List<Face>();
				if (Interface.GetAllFace(wall, ref list, XYZ.BasisZ, null) && list.Count != 0)
				{
					PlanarFace planarFace = null;
					foreach (Face face in list)
					{
						PlanarFace planarFace2 = face as PlanarFace;
						XYZ xyz = planarFace2.FaceNormal();
						if (planarFace2 != null && xyz.Normalize().IsAlmostEqualTo(-XYZ.BasisZ))
						{
							planarFace = planarFace2;
							break;
						}
					}
					if (!(planarFace == null))
					{
						EdgeArrayArray edgeLoops = planarFace.EdgeLoops;
						if (edgeLoops.Size == 1)
						{
                            EdgeArray edgeArray = edgeLoops.get_Item(0);
							foreach (object obj in edgeArray)
							{
								Edge edge = (Edge)obj;
								Curve curve = edge.AsCurve();
								if (curve != null)
								{
									lstCurve.Add(curve);
								}
							}
						}
					}
				}
			}
			catch (Exception)
			{
				throw;
			}
		}

		public static bool IsIntersect(List<XYZ> lstPt1, List<XYZ> lstPt2)
		{
			List<Curve> lstCurve = Interface.CreateLines(lstPt1);
			List<Curve> lstCurve2 = Interface.CreateLines(lstPt2);
			return Interface.IsIntersect(lstCurve, lstCurve2);
		}

		private static bool IsIntersect(List<Curve> lstCurve1, List<Curve> lstCurve2)
		{
			IntersectionResultArray intersectionResultArray = null;
			foreach (Curve curve in lstCurve1)
			{
				foreach (Curve curve2 in lstCurve2)
				{
					curve.Intersect(curve2, out intersectionResultArray);
					if (intersectionResultArray != null && !intersectionResultArray.IsEmpty)
					{
						IntersectionResult intersectionResult = intersectionResultArray.get_Item(0);
						XYZ xyzpoint = intersectionResult.XYZPoint;
						if (xyzpoint != null)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static List<Curve> CreateLines(List<XYZ> lstPt)
		{
			List<Curve> list = new List<Curve>();
			for (int i = 0; i < lstPt.Count; i++)
			{
				Line line;
				if (i == lstPt.Count - 1)
				{
					line = Line.CreateBound(lstPt[i], lstPt[0]);
					list.Add(line);
					return list;
				}
				line = Line.CreateBound(lstPt[i], lstPt[i + 1]);
				if (!(line == null))
				{
					list.Add(line);
				}
			}
			return list;
		}

		public static void DeleteModelGroup(Document doc, ElementId modelGroupId)
		{
			Transaction transaction = new Transaction(doc, "DeleteModelGroup");
			try
			{
				transaction.Start();
				Element element = doc.GetElement(modelGroupId);
				if (element == null)
				{
					transaction.RollBack();
				}
				else
				{
					Group group = element as Group;
					if (group == null)
					{
						transaction.RollBack();
					}
					else
					{
						GroupType groupType = group.GroupType;
						ElementId id = groupType.Id;
						doc.DeleteElement(group);
						doc.DeleteElement(groupType);
						transaction.Commit();
					}
				}
			}
			catch (Exception)
			{
				transaction.RollBack();
			}
		}

		public static bool RefreshOpeningData(DbOpeningBase opening, Dictionary<string, int> dictionary, ref DbOpeningBase outOpening)
		{
			if (opening.m_eHostObject != EHostObject.eArchWall || (opening.m_eCutObject != ECutObject.eHvPipe && opening.m_eCutObject != ECutObject.eWaterPipe && opening.m_eCutObject != ECutObject.ePipeMulti))
			{
				return false;
			}
			OpeningProfileBase profile = opening.m_profile;
			OpeningProfileBase openingProfileBase = null;
			double num = AssistFunc.mmToFeet(300.0);
			bool flag = true;
			if (opening.m_profile is OpeningProfileCircle)
			{
				flag = false;
				OpeningProfileCircle openingProfileCircle = opening.m_profile as OpeningProfileCircle;
				if (!Geometry.Lessthan_Or_Equal(num, openingProfileCircle.m_dCutDiameter + 2.0 * openingProfileCircle.m_dExtendDist))
				{
					return false;
				}
				outOpening = new DbRectWallOpening();
				openingProfileBase = new OpeningProfileRect();
				OpeningProfileRect openingProfileRect = openingProfileBase as OpeningProfileRect;
				openingProfileRect.m_cutHeight = (openingProfileRect.m_cutWidth = openingProfileCircle.m_dCutDiameter);
				outOpening.m_profile = openingProfileBase;
				Interface.SetOpeningExternDist(ref outOpening, dictionary);
			}
			else if (opening.m_profile is OpeningProfileRect)
			{
				OpeningProfileRect openingProfileRect2 = opening.m_profile as OpeningProfileRect;
				if (!Geometry.LessThan(openingProfileRect2.m_cutHeight + 2.0 * openingProfileRect2.m_dExtendDist, num))
				{
					return false;
				}
				outOpening = new DbCircleWallOpening();
				openingProfileBase = new OpeningProfileCircle();
				OpeningProfileCircle openingProfileCircle2 = openingProfileBase as OpeningProfileCircle;
				openingProfileCircle2.m_dCutDiameter = openingProfileRect2.m_cutHeight;
				outOpening.m_profile = openingProfileBase;
				Interface.SetOpeningExternDist(ref outOpening, dictionary);
			}
			openingProfileBase.m_directionCutObj = profile.m_directionCutObj;
			openingProfileBase.m_directionCutObj = profile.m_directionCutObj;
			openingProfileBase.m_directionProfile = profile.m_directionProfile;
			openingProfileBase.m_dPenetrationThickness = profile.m_dPenetrationThickness;
			openingProfileBase.m_position = profile.m_position;
			outOpening.m_dHostWidth = opening.m_dHostWidth;
			outOpening.m_eCutObject = opening.m_eCutObject;
			outOpening.m_eHostObject = opening.m_eHostObject;
			outOpening.m_eSpeciality = opening.m_eSpeciality;
			outOpening.m_strAxisX = opening.m_strAxisX;
			outOpening.m_strAxisY = opening.m_strAxisY;
			outOpening.m_strCreateOpeningDate = opening.m_strCreateOpeningDate;
			outOpening.m_strCutUniqueId = opening.m_strCutUniqueId;
			outOpening.m_strDesignDate = opening.m_strDesignDate;
			outOpening.m_strDesignUser = opening.m_strDesignUser;
			outOpening.m_strFloorPlan = opening.m_strFloorPlan;
			outOpening.m_strGuid = default(Guid).ToString();
			outOpening.m_strHostUniqueId = opening.m_strHostUniqueId;
			outOpening.m_strRemark = opening.m_strRemark;
			if (flag)
			{
				Interface.RefreshOpeningData(outOpening, dictionary, ref outOpening);
			}
			return true;
		}

		public class PointComparer : IComparer<PointSort>
		{
			int IComparer<PointSort>.Compare(PointSort first, PointSort second)
			{
				if (GeoUtil.IsEqual(first.m_dParam, second.m_dParam))
				{
					return 0;
				}
				if (first.m_dParam <= second.m_dParam)
				{
					return -1;
				}
				return 1;
			}
		}
	}
}
